#include <iostream>
#include <vector>
#include <functional>
#include <memory>
#include <unordered_map>
class TimeTask
{
public:
    using TaskFunc=std::function<void()>;
    using RelaseFunc=std::function<void()>;
private:
    uint64_t _id;// 定时器任务ID
    uint32_t _timeout;//超时时间
    TaskFunc _task;//执行任务
    RelaseFunc _rtask;//时间到需要清理的任务
    bool _canceled=false;//是否被清理 true被清理
public:
    TimeTask(uint64_t id,uint32_t timeout,TaskFunc task)
    :_id(id),_timeout(timeout),_task(task)
    {}
    ~TimeTask()
    {
        if (_canceled == false) _task(); 
        _rtask();
    }
    void SetRelaseFunc(const RelaseFunc& cb) {_rtask=cb;} 
    void Cancel() {_canceled=true;}
    uint32_t DelayTime() {return _timeout;}
};

class Timerwheel //时间轮
{
    using WeakTask=std::weak_ptr<TimeTask>;
    using PtrTask =std::shared_ptr<TimeTask>;
private:
    int _tick;//秒针，走到哪里，到哪里释放任务
    int _capacity;//最大容量
    std::vector<std::vector<PtrTask>> _wheel;
    std::unordered_map<uint64_t, WeakTask> _timers;
private:
    void RemoveTimer(uint64_t id) 
    {
        auto it = _timers.find(id);
        if (it != _timers.end()) 
        {
            _timers.erase(it);
        }
    }

public:
    Timerwheel():_tick(0),_capacity(60) {}
    void TimerAdd(uint64_t id,uint32_t delay,TimeTask::TaskFunc cd)
    {
        PtrTask pt(new TimeTask(id,delay,cd));
        pt->SetRelaseFunc(std::bind(&Timerwheel::RemoveTimer, this, id));
        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);
        _timers[id] = WeakTask(pt);
    }
    //刷新/延迟定时任务
    void TimerFlush(uint64_t id)
    {
        auto it=_timers.find(id);
        if(it==_timers.end()) return;
        PtrTask pt = it->second.lock();//
        int delay=pt->DelayTime();//刷新
        int pos=(_tick+delay)%_capacity;
        _wheel[pos].push_back(pt);
        _timers[id]=WeakTask(pt);
    }
    void TimerCancel(uint64_t id)//取消任务
    {
        auto it=_timers.find(id);
        if(it==_timers.end()) return;
        PtrTask pt = it->second.lock();
        if (pt) pt->Cancel();//取消任务
    }
    void RunTimerTask()//向后走
    {
        _tick=(_tick+1)%_capacity;
         _wheel[_tick].clear();//清空指定位置的数组，就会把数组中保存的所有管理定时器对象的shared_ptr释放掉
    }
};

// int main()
// {
//     Timerwheel ti();
//     ti.
// }